package com.xiaoxu.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoxu.base.exception.bkSchoolException;
import com.xiaoxu.content.dao.TeachplanMapper;
import com.xiaoxu.content.dao.TeachplanMediaMapper;
import com.xiaoxu.content.model.dto.SaveTeachplanDto;
import com.xiaoxu.content.model.dto.TeachplanDto;
import com.xiaoxu.content.model.po.Teachplan;
import com.xiaoxu.content.service.TeachplanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 课程计划 服务实现类
 * </p>
 *
 * @author xiaoxu
 */
@Slf4j
@Service
public class TeachplanServiceImpl extends ServiceImpl<TeachplanMapper, Teachplan> implements TeachplanService {

    private final TeachplanMapper teachplanMapper;
    private final TeachplanMediaMapper teachplanMediaMapper;
    /**
     * 注意：一定不要使用构造器注入，否则Spring的三级缓存无法解决循环依赖
     */
    @Autowired
    private  TeachplanService currentProxy;

    public TeachplanServiceImpl(TeachplanMapper teachplanMapper,TeachplanMediaMapper teachplanMediaMapper) {
        this.teachplanMapper = teachplanMapper;
        this.teachplanMediaMapper = teachplanMediaMapper;
    }

    @Override
    public List<TeachplanDto> findTeachplayTree(long courseId) {
        return teachplanMapper.selectTreeNodes(courseId);
    }

    /**
     * 根据教学计划Id删除教学信息
     * @param teachPlanId  课程计划id
     */
    @Override
    @Transactional
    public void deleteTeachplan(Long teachPlanId) {
        Teachplan teachplan = teachplanMapper.selectById(teachPlanId);
        if (teachplan == null){
            throw new bkSchoolException("业务异常，该教学计划不存在");
        }
        //处理移动BUG
        //在删除后将数据库中的orderby重新排序   (不是高性能处理)
        reOrder(teachplan);
        //删除
        int deleteResultCount = teachplanMapper.deleteById(teachPlanId);
        if (deleteResultCount<=0){
            throw new bkSchoolException("业务异常,请检查你所传递的数据，如未发现异常，请联系管理员");
        }
    }

    /**
     * 将教学计划表重新排序
     * @param teachplan 教学任务
     */
    private void reOrder(Teachplan teachplan) {
        Integer orderby = teachplan.getOrderby();
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(Teachplan::getOrderby,orderby);
        queryWrapper.eq(Teachplan::getCourseId,teachplan.getCourseId());
        queryWrapper.eq(Teachplan::getParentid,teachplan.getParentid());
        List<Teachplan> teachplans = teachplanMapper.selectList(queryWrapper);
        if (teachplans == null){
            return;
        }
        teachplans.forEach(item-> moveTeachplanByStep(item,1));
    }

    /**
     * 移动教学计划
     * @param teachPlanId 课程计划Id
     * @param direction  移动方向
     */
    @Override
    public void moveTeachplan(Long teachPlanId, String direction) {
        Teachplan teachplan = teachplanMapper.selectById(teachPlanId);
        if (teachplan == null){
            throw new bkSchoolException("业务异常，未找到该教学计划信息,如有异常，请联系管理员");
        }
        int count = getTeachplanCount(teachplan.getCourseId(), teachplan.getParentid());

        if ("up".equals(direction)){
            if (teachplan.getOrderby() == 1){
                throw new bkSchoolException("操作异常,你不能再向上移动了");
            }
            //上移
            currentProxy.moveTeachplanByStep(teachplan,1);
        }else if("down".equals(direction)){
            //移动前健壮性判断
            if(teachplan.getOrderby() == count){
                throw new bkSchoolException("操作异常,你不能再向下移动了");
            }
            //下移
            currentProxy.moveTeachplanByStep(teachplan,-1);
        }else{
            throw new bkSchoolException("业务异常，移动方位不正确,如有异常，请联系管理员");
        }
    }

    /**
     * 通过步数移动教学计划
     * @param teachplan 教学计划信息
     * @param step 移动步数  整数就是向上移 <-> 负数就是向下移
     */
    @Transactional
    public void moveTeachplanByStep(Teachplan teachplan, int step) {
        //递归结束条件
        if (step == 0){return;}
        //先查出当前教学计划所处的位置
        Integer orderby = teachplan.getOrderby();
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getCourseId, teachplan.getCourseId());
        queryWrapper.eq(Teachplan::getParentid, teachplan.getParentid());
        if (step>0){
            queryWrapper.eq(Teachplan::getOrderby,orderby-1);
        }else{
            queryWrapper.eq(Teachplan::getOrderby,orderby+1);
        }
        Teachplan nextTeachplan = teachplanMapper.selectOne(queryWrapper);

        Integer nextTeachplanOrderby = nextTeachplan.getOrderby();
        nextTeachplan.setOrderby(orderby);
        teachplan.setOrderby(nextTeachplanOrderby);
        //移动
        int deleteCount = teachplanMapper.deleteBatchIds(Arrays.asList(teachplan.getId(), nextTeachplan.getId()));
        int insert = teachplanMapper.insert(teachplan);
        int insert1 = teachplanMapper.insert(nextTeachplan);
        if (insert1<=0 || insert<=0 || deleteCount<=0){
            throw new bkSchoolException("业务异常，移动失败，请检查是否操作正确，如有异常，请联系管理员");
        }
        //递归
        if (step >0){
            moveTeachplanByStep(teachplan,step-1);
        }else{
            moveTeachplanByStep(teachplan,step+1);
        }
    }

    /**
     * 保存或修改教学计划
     * @param teachplanDto  课程计划信息
     */
    @Override
    @Transactional
    public void saveOrUpdateTeachplan(SaveTeachplanDto teachplanDto) {
        //课程计划id
        Long id = teachplanDto.getId();
        Teachplan teachplan = teachplanMapper.selectById(id);
        //修改课程计划
        if (teachplan != null) {
            BeanUtils.copyProperties(teachplanDto, teachplan);
            int updateResultCount = teachplanMapper.updateById(teachplan);
            if (updateResultCount<=0){
                throw new bkSchoolException("业务异常,数据修改失败，请联系管理员");
            }
        } else {
            //取出同父同级别的课程计划数量
            int count = getTeachplanCount(teachplanDto.getCourseId(), teachplanDto.getParentid());
            teachplan = new Teachplan();
            //设置排序号
            teachplan.setOrderby(count + 1);
            BeanUtils.copyProperties(teachplanDto, teachplan);
            int insertResultCount = teachplanMapper.insert(teachplan);
            if (insertResultCount<=0){
                throw new bkSchoolException("业务异常,数据新增失败，请联系管理员");
            }
        }

    }

    /**
     * @param courseId 课程id
     * @param parentId 父课程计划id
     * @return int 最新排序号
     * @description 获取最新的排序号
     * @author xiaoxu
     * @date 2023/1/17 22:43
     */
    private int getTeachplanCount(long courseId, long parentId) {
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getCourseId, courseId);
        queryWrapper.eq(Teachplan::getParentid, parentId);
        return teachplanMapper.selectCount(queryWrapper);
    }

}
